package source;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;

/**
 *
 * @author Sabitov Artem
 */
public class mpServer {
	// переменные отвечающие за структуру сервера
	private ArrayList<String> BodyFile = new ArrayList<>();
	private ArrayList<String> HeadFile = new ArrayList<>();
	private ArrayList<String> Crew = new ArrayList<>();
	private ArrayList<String> Vessel = new ArrayList<>();
	private HashMap<String, ArrayList<String>> CrewSection = new HashMap<>();
	private HashMap<String, ArrayList<String>> VesselSection = new HashMap<>();
	private int	iCrewCounter;
	private int iVesselCounter;
	// общие переменные класса
	private String sServerPath;
	private int iTimeSync;
	private boolean bEndFile;
	
    mpServer(String sArgServerPath, int iArgTimeSync) {
		sServerPath = sArgServerPath;
		iTimeSync = iArgTimeSync;
		buildServer(false);
	}
	
	public void syncServer(int iClientID, HashMap clientCrews, HashMap clientVessels) {
		srvLog("received update from client. ID:" + iClientID);
		srvLog("update crews.");
		CrewSection = mpSync.syncCrews(CrewSection, clientCrews, true);
		srvLog("update vessels.");
		VesselSection = mpSync.syncVessels(VesselSection, clientVessels, true);
		srvLog("sync with clients.");
		for(int i = 0; i < mpMain.getClientCount(); i++) {
			if(i != iClientID) {
				mpMain.getClient(i).syncClient(CrewSection, VesselSection);
			}
		}
	}
	
	private void buildServer(boolean bReBuild) {
		log("");
		if(bReBuild) {
			srvLog("update server.");
		} else {
			srvLog("build server.");
		}
		// заполняем структуры, собираем объект
		try {
			Scanner sc = new Scanner(new File(sServerPath));
			String sNextLine;
			Object oObj;
			// читаем все содержимое файла
			// заполняем счетчики кораблей, экипажей
			do {
				try {
					sNextLine = sc.nextLine();
					BodyFile.add(sNextLine);
					switch (sNextLine) {
						case mpPattern.CREW:
							iCrewCounter++;
							break;
						case mpPattern.VESSEL:
							iVesselCounter++;
							break;
					}
				} catch (NoSuchElementException ex) {
					log(this.toString() + " file: " + sServerPath + " read succesfully.");
					bEndFile = true;
				}
			} while (!bEndFile);
			// заполняем структуры объекта файла-сервера
			int iCrewIndex = 0;
			int iVesselIndex = 0;
			for (Iterator it = BodyFile.iterator(); it.hasNext();) {
				oObj = it.next();
				switch (oObj.toString()) {
					// нашли экипаж
					case mpPattern.CREW:
						// добавляем секцию экипажа в строрайдж
						buildSection(oObj, Crew, it);
						CrewSection.put(Crew.get(2), Crew);
						Crew = new ArrayList<>();
						iCrewIndex++;
						break;
					// нашли корабль
					case mpPattern.VESSEL:
						// добавляем секцию корабля в строрайдж
						buildSection(oObj, Vessel, it);
						VesselSection.put(Vessel.get(2), Vessel);
						Vessel = new ArrayList<>();
						iVesselIndex++;
						break;
					// все остальное кидаем в заголовок
					default:
						HeadFile.add(oObj.toString());
						break;
				}
			}
			// удалим последнюю скобку
			HeadFile.remove(HeadFile.size() - 1);
			HeadFile.remove(HeadFile.size() - 1);
			sc.close();
		// обработка исключения	
		} catch (FileNotFoundException ex) {
			log("class: " + mpServer.class.getName() + " file: " + sServerPath + " read failure.");
		}
		//srvLog("building server succesfully..");
	}	
	
	// собирает секцию для сторайджа
	private ArrayList<String> buildSection(Object oObj, ArrayList<String> List, Iterator it) {
		List.add(oObj.toString());
		int iBraceCount = 0;
		do {
			oObj = it.next();
			switch (oObj.toString().trim()) {
				case "{":
					List.add(oObj.toString());
					iBraceCount++;
					break;
				case "}":
					List.add(oObj.toString());
					iBraceCount--;
					break;
				default:
					List.add(oObj.toString());
					break;
			}
		} while (iBraceCount != 0);
		return List;
	}

	public String getServerPath() {
		return sServerPath;
	}
	
	// дебаг
	public void log(Object oObj) {
		mpLog.dbgLog(oObj);
	}
	// лог
	public void srvLog(Object oObj) {
		mpLog.srvLog(this, oObj);
	}
}
